package com.ruoyi.complex.service.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.complex.mapper.ComplexScoreFormMapper;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.complex.constant.ComplexDirectoryIsExport;
import com.ruoyi.complex.domain.ComplexDirectory;
import com.ruoyi.complex.domain.ComplexScoreForm;
import com.ruoyi.complex.dto.ComplexItemVO;
import com.ruoyi.complex.dto.ExcelColumn;
import com.ruoyi.complex.dto.ScoreFormVO;
import com.ruoyi.complex.service.IComplexScoreFormService;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;

/**
 * 学生表单Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-04-25
 */
@Service
public class ComplexScoreFormServiceImpl implements IComplexScoreFormService {
    @Autowired
    private ComplexScoreFormMapper complexScoreFormMapper;

    @Autowired
    private ComplexDirectoryServiceImpl directoryServiceImpl;

    /**
     * 查询学生表单
     * 
     * @param scoreId 学生表单主键
     * @return 学生表单
     */
    @Override
    public ComplexScoreForm selectComplexScoreFormByScoreId(Long scoreId) {
        return complexScoreFormMapper.selectComplexScoreFormByScoreId(scoreId);
    }

    /**
     * 查询学生表单列表
     * 
     * @param complexScoreForm 学生表单
     * @return 学生表单
     */
    @Override
    public List<ComplexScoreForm> selectComplexScoreFormList(ComplexScoreForm complexScoreForm) {
        return complexScoreFormMapper.selectComplexScoreFormList(complexScoreForm);
    }

    /**
     * 新增学生表单
     * 
     * @param complexScoreForm 学生表单
     * @return 结果
     */
    @Override
    public int insertComplexScoreForm(ComplexScoreForm complexScoreForm) {
        complexScoreForm.setCreateTime(DateUtils.getNowDate());
        complexScoreForm.setUserId(SecurityUtils.getUserId());
        complexScoreForm.setStudentNumber(SecurityUtils.getUsername());
        complexScoreForm.setCreateBy(SecurityUtils.getUsername());
        return complexScoreFormMapper.insertComplexScoreForm(complexScoreForm);
    }

    /**
     * 修改学生表单
     * 
     * @param complexScoreForm 学生表单
     * @return 结果
     */
    @Override
    public int updateComplexScoreForm(ComplexScoreForm complexScoreForm) {
        return complexScoreFormMapper.updateComplexScoreForm(complexScoreForm);
    }

    /**
     * 批量删除学生表单
     * 
     * @param scoreIds 需要删除的学生表单主键
     * @return 结果
     */
    @Override
    public int deleteComplexScoreFormByScoreIds(Long[] scoreIds) {
        return complexScoreFormMapper.deleteComplexScoreFormByScoreIds(scoreIds);
    }

    /**
     * 删除学生表单信息
     * 
     * @param scoreId 学生表单主键
     * @return 结果
     */
    @Override
    public int deleteComplexScoreFormByScoreId(Long scoreId) {
        return complexScoreFormMapper.deleteComplexScoreFormByScoreId(scoreId);
    }

    public List<Map<ExcelColumn, String>> exportExcelData(ComplexScoreForm complexScoreForm) {
        // 获取导出的表单
        List<ComplexScoreForm> list = complexScoreFormMapper.selectComplexScoreFormList(complexScoreForm);
        // 获取所有目录
        List<ComplexDirectory> directoryList = directoryServiceImpl.selectComplexDirectoryList(null);
        // 根据父目录Id分组
        Map<Long, List<ComplexDirectory>> groubed = directoryList.stream()
                .collect(Collectors.groupingBy(ComplexDirectory::getParentId));
        // 获取所有需要导出分数的目录
        ComplexDirectory temp = new ComplexDirectory();
        temp.setIsExport(ComplexDirectoryIsExport.EXPORT);
        List<ComplexDirectory> exportDirectories = directoryServiceImpl.selectComplexDirectoryList(temp);
        // 获取表单集合
        List<Map<ExcelColumn, String>> listMap = new ArrayList<>();
        /* List<ScoreFormVO> formVOs = */list.stream().map(item -> {
            ScoreFormVO scoreFormVO = new ScoreFormVO();
            scoreFormVO.setCommitFlag(item.getCommitFlag());
            scoreFormVO.setStudentClass(item.getStudentClass());
            scoreFormVO.setStudentNumber(item.getStudentNumber());
            List<ComplexItemVO> array = JSONArray.parseArray(item.getScoreJson(), ComplexItemVO.class);
            scoreFormVO.setItemVOs(array);
            return scoreFormVO;
        }).forEach(item -> {
            Map<ExcelColumn, String> map = new HashMap<>();
            ExcelColumn classColumn = new ExcelColumn();
            classColumn.setColumnName("班级");
            classColumn.setOrder(9L);
            classColumn.setValue("班级");
            ExcelColumn stuNumberColumn = new ExcelColumn();
            stuNumberColumn.setColumnName("学号");
            stuNumberColumn.setOrder(10L);
            stuNumberColumn.setValue("学号");
            map.put(classColumn, item.getStudentClass());
            map.put(stuNumberColumn, item.getStudentNumber());
            for (ComplexDirectory export : exportDirectories) {
                Double currentDirectoryScore = getCurrentDirectoryScore(export, groubed, item.getItemVOs());
                ExcelColumn excelColumn = new ExcelColumn();
                excelColumn.setColumnName(export.getDirectoryName());
                excelColumn.setOrder(export.getOrderNumber());
                excelColumn.setValue(export);
                map.put(excelColumn, String.format("%.2f", currentDirectoryScore));
            }
            listMap.add(map);
        });
        return listMap;
    }

    private Double getCurrentDirectoryScore(ComplexDirectory exportDirectory, Map<Long, List<ComplexDirectory>> groubed,
            List<ComplexItemVO> itemVOs) {
        // 获取所有子目录和当前目录的Id
        List<Long> allChildrenDirectories = getAllChildrenDirectories(exportDirectory.getDirectoryId(), groubed);
        // 求和
        double sum = itemVOs.stream().filter(item -> {
            return allChildrenDirectories.contains(item.getDirectoryId());
        }).mapToDouble(item -> {
            Double itemScore = item.getItemScore();
            Long addTimes = item.getAddTimes();
            if (itemScore != null && addTimes != null) {
                return itemScore.doubleValue() * addTimes.longValue();
            }
            return 0.0;
        }).sum();
        return Double.valueOf(sum);
    }

    private List<Long> getAllChildrenDirectories(Long currentId, Map<Long, List<ComplexDirectory>> groubed) {
        List<Long> totalList = new ArrayList<>();
        totalList.add(currentId);
        List<ComplexDirectory> list = groubed.get(currentId);
        if (list == null) {
            return totalList;
        }
        for (ComplexDirectory each : list) {
            totalList.add(each.getDirectoryId());
        }
        for (ComplexDirectory item : list) {
            List<Long> allChildrenDirectories = getAllChildrenDirectories(item.getDirectoryId(), groubed);
            totalList.addAll(allChildrenDirectories);
        }
        return totalList;
    }

    public String handleExport(List<Map<ExcelColumn, String>> data) {
        Workbook workbook = new XSSFWorkbook();
        ComplexDirectory temp = new ComplexDirectory();
        temp.setIsExport(ComplexDirectoryIsExport.EXPORT);
        List<ComplexDirectory> exportDirectories = directoryServiceImpl.selectComplexDirectoryList(temp);

        Map<String, List<ComplexDirectory>> grouped = exportDirectories.stream()
                .collect(Collectors.groupingBy(ComplexDirectory::getAncestorName));
        for (String key : grouped.keySet()) {
            Sheet sheet = workbook.createSheet(key);
            List<ExcelColumn> headTemp = data.get(0).keySet().stream().filter(item -> {
                if ("班级".equals(item.getValue().toString()) || "学号".equals(item.getValue().toString())) {
                    return true;
                } else {
                    ComplexDirectory complexDirectory = (ComplexDirectory) item.getValue();
                    return complexDirectory.getAncestorName().equals(key);
                }
            }).collect(Collectors.toList());
            List<ExcelColumn> sortedHead = ListUtil.sortByProperty(headTemp, "order");
            ListUtil.reverse(sortedHead);
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < sortedHead.size(); i++) {
                headerRow.createCell(i).setCellValue(sortedHead.get(i).getColumnName());
            }
            int rowIndex = 1;
            for (Map<ExcelColumn, String> map : data) {
                Set<ExcelColumn> keySet = map.keySet();
                // List<ExcelColumn> sortedColumn = ListUtil.sortByProperty(List.copyOf(keySet),
                // "order");
                List<ExcelColumn> collect = keySet.stream().filter(item -> {
                    if ("班级".equals(item.getValue().toString()) || "学号".equals(item.getValue().toString())) {
                        return true;
                    } else {
                        ComplexDirectory complexDirectory = (ComplexDirectory) item.getValue();
                        return complexDirectory.getAncestorName().equals(key);
                    }
                }).collect(Collectors.toList());
                List<ExcelColumn> sortedColumns = ListUtil.sortByProperty(collect, "order");
                ListUtil.reverse(sortedColumns);
                Row dataRow = sheet.createRow(rowIndex++);
                for (int i = 0; i < sortedColumns.size(); i++) {
                    dataRow.createCell(i).setCellValue(map.get(sortedColumns.get(i)));
                }
            }
            for (int j = 0; j < sortedHead.size(); j++) {
                sheet.setColumnWidth(j, 6000);
            }
        }
        // 保存 Excel 文件
        String filePath = "/generate" + "/" + DateUtils.datePath();
        new File(filePath).mkdirs();
        String fileName = IdUtil.fastSimpleUUID() + ".xlsx";
        try (FileOutputStream fos = new FileOutputStream(filePath + "/" + fileName)) {
            workbook.write(fos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 关闭工作簿
        try {
            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return filePath + "/" + fileName;
    }
}
